use once_cell::sync::Lazy;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use sync_clipboard_client::ClipboardContent;
// use sync_clipboard_client::config::config::get_config;
use sync_clipboard_client::model::database::{Database, User};
use sync_clipboard_client::network::{Client, SyncData};
use sync_clipboard_client::{
    Clipboard, ClipboardContext, ClipboardHandler, ClipboardWatcher, ClipboardWatcherContext,
};
use tokio::sync::Mutex;
struct Manager {
    ctx: ClipboardContext,
    suppress_events:  Arc<AtomicBool>,
}

impl Manager {
    pub fn new() -> Self {
        let ctx = ClipboardContext::new().unwrap();
        Manager {
            ctx,
            suppress_events: Arc::new(AtomicBool::new(false)), // 初始化时不抑制事件
        }
    }
}
static CLIENT: Lazy<Arc<Mutex<Option<Arc<Client>>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));
static USER: Lazy<Arc<Mutex<Option<User>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));
static LAST_UPDATE: Lazy<Mutex<(i64, ClipboardContent)>> =
    Lazy::new(|| Mutex::new((0, ClipboardContent::Text("".to_string()))));
async fn init_client() -> Client {
    // Client::new("ws://127.0.0.1:20505").await
    Client::new("ws://150.158.107.119:20505").await
}
use std::time::{SystemTime, UNIX_EPOCH};

impl ClipboardHandler for Manager {
    fn on_clipboard_change(&mut self) {
        let suppress = self.suppress_events.clone();
        if suppress.load(Ordering::Relaxed) {
            suppress.store(false, Ordering::Relaxed);
            return;
        }
        drop(suppress);
        let content = match (self.ctx.get_text(), self.ctx.get_files()) {
            (Ok(text), _) if !text.is_empty() => ClipboardContent::Text(text),
            (_, Ok(files)) if !files.is_empty() => ClipboardContent::Files(files),
            _ => return,
        };
        let client = CLIENT.clone();
        tokio::spawn(async move {
            let binding = client.lock().await;
            let current_time = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .expect("时间倒退")
                .as_millis() as i64;
            if let Err(e) = binding
                .as_ref()
                .unwrap()
                .sync_to_server(&content, current_time)
                .await
            {
                eprintln!("Sync failed: {}", e);
            } else {
                *LAST_UPDATE.lock().await = (current_time, content);
            }
        });
    }
}
#[tokio::main]
async fn main() {
    let manager = Manager::new();
        
    let (client, user) = (CLIENT.clone(), USER.clone());
    {
        let mut db = Database::new("data.db").unwrap();
        let a = db.query_all_users().unwrap();
        println!("{:?}", a);
        if a.len() == 0 {
            println!("请先注册 : username");
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).unwrap();
            let user = User::new(
                input.trim().to_string(),
                "test".to_string(),
                "test".to_string(),
                "test".to_string(),
                "test".to_string(),
            );
            db.insert_user(&user).unwrap();
        }
        let once_client = Arc::new(init_client().await);
        {
            let mut guard = client.lock().await;
            *guard = Some(Arc::clone(&once_client));
        }
        let suppress_events = Arc::clone(&manager.suppress_events);
        (&*once_client)
            .receive_loop(Box::new(move |content| {
                let clipboard_context = ClipboardContext::new();
                let suppress_events = Arc::clone(&suppress_events);
                match content {
                    ClipboardContent::Text(text) => Box::pin(async move {
                        let raw_data: SyncData = serde_json::from_str(&text).unwrap();
                        {
                            let mut local = LAST_UPDATE.lock().await;
                            if raw_data.timestamp > local.0 { // 服务器数据更新
                                println!("更新本地数据");
                                *local = (
                                    raw_data.timestamp,
                                    ClipboardContent::Text(raw_data.data.clone()),
                                );
                                // 
                                suppress_events.store(true, Ordering::Relaxed);
                                clipboard_context
                                    .unwrap()
                                    .set_text(raw_data.data)
                                    .expect("Failed to set text");
                            }
                        }
                    }),
                    _ => Box::pin(async {
                        println!("收到其他类型");
                    }),
                }
            }))
            .await;
        let mut user = user.lock().await;
        *user = a.get(0).cloned();
    }
    // let mut history = ClipboardHistory::new();
    // let address =  &get_config().unwrap().server.address;
    let mut watcher = ClipboardWatcherContext::new().unwrap();
    let _watcher_shutdown: sync_clipboard_client::WatcherShutdown =
        watcher.add_handler(manager).get_shutdown_channel();

    // thread::spawn(move || {
    // 	thread::sleep(Duration::from_secs(5));
    	// _watcher_shutdown.stop();
    // });


    watcher.start_watch();
}
